package tools.retrytools;

import lombok.SneakyThrows;
import org.apache.commons.lang3.RandomUtils;

import java.util.function.Function;

public class RetryUtils {
    public static void retry(Action action, int retryCount) {
        int retry = 0;
        while (true) {
            try {
                action.apply();
                return;
            } catch (Throwable e) {
                if (retry++ < retryCount) {
                    continue;
                }
                int wait = RandomUtils.nextInt(0, 1 << retry) * 100;
                ThreadUtils.sleep(wait);
                throw e;
            }
        }
    }

    @SneakyThrows
    public static void retry(Action action, int retryCount, ExceptionUtil.RethrowConsumer<Throwable> errorHandler) {
        try {
            retry(action, retryCount);
        } catch (Throwable e) {
            errorHandler.accept(e);
        }
    }

    public static <T, R> Function<T, R> retryFun(Function<T, R> fun, int retryCount, int sleepMutiply, ExceptionUtil.RethrowConsumer<Throwable> errorHandler) {
        return arg -> {
            int retry = 0;
            while (true) {
                try {
                    return fun.apply(arg);
                } catch (Throwable e) {
                    if (retry++ < retryCount) {
                        continue;
                    }
                    int wait = RandomUtils.nextInt(0, 1 << retry) * sleepMutiply;
                    ThreadUtils.sleep(wait);
                    throw e;
                }
            }
        };
    }

}
